package cn.edu.cuit.elena.web.service;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.edu.cuit.elena.common.Configuration;
import cn.edu.cuit.elena.common.SackConstants;
import cn.edu.cuit.elena.db.DataSource;
import cn.edu.cuit.elena.db.DataSourceFactory;
import cn.edu.cuit.elena.trace.Tracer;
import cn.edu.cuit.elena.transaction.DataSourceManager;
import cn.edu.cuit.elena.transaction.system.UserContext;
import cn.edu.cuit.elena.web.System;
import cn.edu.cuit.elena.web.service.ServiceServlet.ServiceConstants;
import cn.edu.cuit.elena.web.tool.CommonHelper;
import cn.edu.cuit.elena.web.tool.JsonHelper;

public class DataSourceManagementServlet
    extends HttpServlet
{

    static final String ADD_DATASOURCE = "add";
    static final String UPDATE_DATASOURCE = "update";
    static final String DELETE_DATASOURCE = "delete";
    static final String LOAD_DATASOURCE = "loaddatasource";
    static final String MIGRATION = "migration";

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    /**
     * Constructor of the object.
     */
    public DataSourceManagementServlet()
    {
        super();
    }

    /**
     * Destruction of the servlet. <br>
     */
    public void destroy()
    {
        super.destroy(); // Just puts "destroy" string in log
        // Put your code here
    }

    /**
     * The doGet method of the servlet. <br>
     * 
     * This method is called when a form has its tag value method equals to get.
     * 
     * @param request
     *            the request send by the client to the server
     * @param response
     *            the response send by the server to the client
     * @throws ServletException
     *             if an error occurred
     * @throws IOException
     *             if an error occurred
     */
    public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException
    {

        doPost( request, response );
    }

    /**
     * The doPost method of the servlet. <br>
     * 
     * This method is called when a form has its tag value method equals to post.
     * 
     * @param request
     *            the request send by the client to the server
     * @param response
     *            the response send by the server to the client
     * @throws ServletException
     *             if an error occurred
     * @throws IOException
     *             if an error occurred
     */
    public void doPost( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException
    {

        response.setContentType( "text/html" );
        response.setCharacterEncoding( "utf-8" );
        PrintWriter out = response.getWriter();
        String para = request.getParameter( "kind" );

        if( ADD_DATASOURCE.equals( para ) )
        {
            String username = request.getParameter( "username" );
            String password = request.getParameter( "password" );
            String name = request.getParameter( "name" );
            String url = request.getParameter( "url" );
            String database = request.getParameter( "database" );

            //Construct configuration.
            Map<String, String> configuration = new HashMap<String, String>();
            configuration.put( SackConstants.USER_NAME, username );
            configuration.put( SackConstants.PASS_WORD, password );
            configuration.put( SackConstants.SCHEMA_NAME, name );
            configuration.put( SackConstants.URL, url );
            configuration.put( SackConstants.DRIVER, CommonHelper.matchDriver( database ) );
            configuration.put( SackConstants.VENDER, CommonHelper.matchVender( database ) );//TODO
            //            configuration.put( SackConstants.DATASOURCE_ID,xxxx );//TODO

            try
            { //Create data source.
                DataSource dataSource = DataSourceFactory.createDataSourceByConfiguration( Configuration
                    .create( configuration ) );
                UserContext userContext = (UserContext) request.getSession().getAttribute(
                    ServiceConstants.USERCONTEXT.mark() );
                userContext.getDataSourceManager().define( dataSource );
                out.write( SackConstants.SUCCESS );
                out.flush();
                out.close();
            }
            catch( Exception e )
            {
                Tracer
                    .fatalTrace( DataSourceManagementServlet.class, "DataSource.svt exception : " + e.getMessage(), e );
                //Send msg.
                out.write( SackConstants.FAILURE );
                out.flush();
                out.close();
            }
        }
        else if( UPDATE_DATASOURCE.equals( para ) )
        {

        }
        else if( DELETE_DATASOURCE.equals( para ) )
        {
            try
            {
                String username = request.getParameter( "b_username" );
                String password = request.getParameter( "b_password" );
                String driver = request.getParameter( "b_driver" );
                String url = request.getParameter( "b_url" );
                String userid = ( (UserContext) request.getSession().getAttribute( ServiceConstants.USERCONTEXT.mark() ) )
                    .getUserName();

                //                System.getBaseDao().insertOneRow( SackConstants.SQL.DELETE_DATASOURCE_OF_USER.sql(),
                //                    Arrays.asList( userid, username, url, password, driver ) );

                Map<String, String> map = new HashMap<String, String>();
                map.put( SackConstants.USER_NAME, username );
                map.put( SackConstants.PASS_WORD, password );
                map.put( SackConstants.DRIVER, driver );
                map.put( SackConstants.URL, url );

                DataSource dataSource = DataSourceFactory.createDataSourceByConfiguration( Configuration.create( map ),
                    true );
                ( (UserContext) request.getSession().getAttribute( ServiceConstants.USERCONTEXT.mark() ) )
                    .getDataSourceManager().discard( dataSource );

                Tracer.debugTrace( DataSourceManagementServlet.class,
                    "DataSourceManagementServlet delete datasource in DB : " + userid + " " + username + " " + url
                        + " " + password + " " + driver, null );

                out.write( SackConstants.SUCCESS );
                out.flush();
                out.close();
            }
            catch( Exception e )
            {
                Tracer.fatalTrace( DataSourceManagementServlet.class, "Exception" + e.getMessage(), e );
                out.write( SackConstants.FAILURE );
                out.flush();
                out.close();
            }

        }
        else if( LOAD_DATASOURCE.equals( para ) )
        {
            UserContext userContext = (UserContext) request.getSession().getAttribute(
                ServiceConstants.USERCONTEXT.mark() );
            List<Map<String, String>> result = System.getBaseDao().queryForMap(
              SackConstants.SQL.SELECT_DATASOURCES_OF_USER.sql(), userContext.getUserName() );

//            List<Map<String, String>> result = new LinkedList<Map<String, String>>();
//            for( DataSource d : userContext.getDataSourceManager().getDataSources() )
//            {
//                Map<String, String> map = new HashMap<String, String>();
//                map.put( "username", d.getUserName() );
//                map.put( "state", d.getState() );
//                map.put( "driver", d.getDriver() );
//                map.put( "vender", d.getVender() );
//                map.put( "password", d.getPassWord() );
//                map.put( "url", d.getUrl() );
//                map.put( "schemaname", d.getName() );
//                result.add( map );
//            }

            String json = JsonHelper.getNewInstance().toJson( result );
            Tracer.debugTrace( DataSourceManagementServlet.class, "DataSourceManagementServlet json : " + json, null );
            out.write( json );
            out.flush();
            out.close();
        }
        else if( MIGRATION.equals( para ) )
        {
            try
            {
                String username = request.getParameter( "b_username" );
                String password = request.getParameter( "b_password" );
                String driver = request.getParameter( "b_driver" );
                String url = request.getParameter( "b_url" );
                String schemaname = request.getParameter( "b_schemaname" );
                UserContext userContext = ( (UserContext) request.getSession().getAttribute(
                    ServiceConstants.USERCONTEXT.mark() ) );

                Map<String, String> configurable = new HashMap<String, String>();
                configurable.put( SackConstants.USER_NAME, username );
                configurable.put( SackConstants.PASS_WORD, password );
                configurable.put( SackConstants.URL, url );
                configurable.put( SackConstants.DRIVER, driver );
                configurable.put( SackConstants.SCHEMA_NAME, schemaname );

                try
                {
                    //                    dataSource = userContext.getDataSourceManager().define(
                    //                        DataSourceFactory.createDataSourceByConfiguration( Configuration.create( configurable ) ) );

                    for( DataSource dataSource2 : userContext.getDataSourceManager().getDataSources() )
                    {
                        if( dataSource2.toString().equals( url + username + password + driver ) )
                        {
                            if( !userContext.caches( dataSource2 ) )
                            {
                                out.write( SackConstants.DUPLICATED );
                                out.flush();
                                out.close();
                            }
                            else
                            {
                                out.write( SackConstants.SUCCESS );
                                out.flush();
                                out.close();
                                break;
                            }
                        }
                    }
                }
                catch( Exception e )
                {
                    Tracer.fatalTrace( DataSourceManagementServlet.class,
                        "DataSourceManagementServlet miguration exception due to : " + e.getMessage(), e );
                    out.write( SackConstants.FAILURE );
                    out.flush();
                    out.close();
                }
            }
            catch( Exception e )
            {
                Tracer.debugTrace( DataSourceManagementServlet.class, "DataSourceManagementServlet Migration failed : "
                    + e.getCause(), e );
                out.write( SackConstants.FAILURE );
                out.flush();
                out.close();
            }
        }
    }

    /**
     * Initialization of the servlet. <br>
     * 
     * @throws ServletException
     *             if an error occurs
     */
    public void init() throws ServletException
    {
        // Put your code here
    }

}
